package com.han.jdbc.mysql.xa;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.sql.XAConnection;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

import com.mysql.jdbc.jdbc2.optional.MysqlXAConnection;
import com.mysql.jdbc.jdbc2.optional.MysqlXid;

/**
* @author hanpeng
* @version 创建时间：2020年7月12日 下午11:07:53
* @ClassName 类名称
* @Description 类描述 关于XA mysql实现
	https://dev.mysql.com/doc/refman/5.7/en/xa.html
*/
public class XATest {
	public static void main(String[] args) throws SQLException {
		//true表示打印XA语句,，用于调试
	      boolean logXaCommands = true;
	      // 获得资源管理器操作接口实例 RM1
	      Connection conn1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "shxx12151022");
	      XAConnection xaConn1 = new MysqlXAConnection((com.mysql.jdbc.Connection) conn1, logXaCommands);
	      XAResource rm1 = xaConn1.getXAResource();
	      // 获得资源管理器操作接口实例 RM2
	      Connection conn2 = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root",
	            "shxx12151022");
	      XAConnection xaConn2 = new MysqlXAConnection((com.mysql.jdbc.Connection) conn2, logXaCommands);
	      XAResource rm2 = xaConn2.getXAResource();
	      // AP请求TM执行一个分布式事务，TM生成全局事务id
	      byte[] gtrid = "g12345".getBytes();
	      int formatId = 1;
	      try {
	         // ==============分别执行RM1和RM2上的事务分支====================
	         // TM生成rm1上的事务分支id
	         byte[] bqual1 = "b00001".getBytes();
	         Xid xid1 = new MysqlXid(gtrid, bqual1, formatId);
	         // 执行rm1上的事务分支
	         rm1.start(xid1, XAResource.TMNOFLAGS);//One of TMNOFLAGS, TMJOIN, or TMRESUME.
	         PreparedStatement ps1 = conn1.prepareStatement("INSERT into user(name) VALUES ('tianshouzhi')");
	         ps1.execute();
	         rm1.end(xid1, XAResource.TMSUCCESS);
	         // TM生成rm2上的事务分支id
	         byte[] bqual2 = "b00002".getBytes();
	         Xid xid2 = new MysqlXid(gtrid, bqual2, formatId);
	         // 执行rm2上的事务分支
	         rm2.start(xid2, XAResource.TMNOFLAGS);
	         PreparedStatement ps2 = conn2.prepareStatement("INSERT into user(name) VALUES ('wangxiaoxiao')");
	         ps2.execute();
	         rm2.end(xid2, XAResource.TMSUCCESS);
	         // ===================两阶段提交================================
	         // phase1：询问所有的RM 准备提交事务分支
	         int rm1_prepare = rm1.prepare(xid1);
	         int rm2_prepare = rm2.prepare(xid2);
	         // phase2：提交所有事务分支
	         boolean onePhase = false; //TM判断有2个事务分支，所以不能优化为一阶段提交
	         if (rm1_prepare == XAResource.XA_OK
	               && rm2_prepare == XAResource.XA_OK
	               ) {//所有事务分支都prepare成功，提交所有事务分支
	            rm1.commit(xid1, onePhase);
	            rm2.commit(xid2, onePhase);
	         } else {//如果有事务分支没有成功，则回滚
	            rm1.rollback(xid1);
	            rm1.rollback(xid2);
	         }
	      } catch (XAException e) {
	         // 如果出现异常，也要进行回滚
	         e.printStackTrace();
	      }
	}
}
